//
//  TBProcessNodeMC.m
//  TBShare
//
//  Created by JIENING ZHANG on 2020/2/25.
//  Copyright © 2020 taobao. All rights reserved.
//

#import "TBProcessNodeMC.h"
#import "TBProcessChainMC.h"

void excuteInQueue(BOOL useMainQueue, void (^ _Nullable block)(void)) {
    if(useMainQueue) {
        dispatch_async(dispatch_get_main_queue(), block);
    } else {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), block);
    }
}

// 主线程执行block
void excuteInMainQueue(void (^ _Nullable block)(void))
{
//    if ([NSThread isMainThread]) {
//        block();
//    }else{
        dispatch_async(dispatch_get_main_queue(), block);
//    }
}

// 非主线程执行block
void excuteInGlobleQueue(void (^ _Nullable block)(void))
{
//    if (![NSThread isMainThread]) {
//        block();
//    }else{
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), block);
//    }
}


@interface TBProcessNodeMC ()

// 并联前置节点数组，偶数下标存放前置节点对象，奇数下标存放前置节点和自身的强弱关系
@property (nonatomic, strong) NSMutableArray *preNodeList;
@property (nonatomic, assign) int cx;
@property (nonatomic, assign) int cy;
@end

@implementation TBProcessNodeMC

- (instancetype)init {
    if (self = [super init]) {
        _preNodeList = [NSMutableArray array];
        _timeOut4Process = -1.f;
        
        _cx = -1;
        _cy = -1;
    }
    return self;
}

- (void)dealloc {
    [_preNodeList removeAllObjects];
    _preNodeList = nil;
}

-(NSString *)name4log {
    if([_nodeName length] > 0) {
        return _nodeName;
    }
    return NSStringFromClass([self class]);
}

-(CGPoint) getNodeCordinate4Chain {
    return CGPointMake(_cx, _cy);
}

-(NSArray *)getPreNodeList {
    if(_preNodeList) {
        return [_preNodeList copy];
        /*
        NSMutableArray *nodeList = [NSMutableArray array];
        for(int loop=0; loop < [_preNodeList count]; loop += 2) {
            TBProcessNodeMC* node = (TBProcessNodeMC*) (_preNodeList[loop]);
            [nodeList addObject:node];
        }
        return nodeList;
        //*/
    }
    return nil;
}

//- (BOOL)isEqual:(id)object {
//    return (object == self);
//}

- (BOOL)isWorkStatusFinish {
    return (_processStatus == TBProcessNodeMCStatusGoDie ||
            _processStatus == TBProcessNodeMCStatusGoSucc);
}

-(void) forceBegin {

    //this.logEvent(this.getClass().getSimpleName() + " forceBegin");
    _processStatus = TBProcessNodeMCStatusWorking;
    
    if(_timeOut4Process > 0.f) {
        // 超时逻辑
        __weak typeof(self) wSelf = self;
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_timeOut4Process * NSEC_PER_SEC)),
                       (self.forceMainThread ? dispatch_get_main_queue() : dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)),
                       ^{
                            if(! wSelf) {
                                NSLog(@"(--) timeout, wSelf==nil, no operation");
                                return;
                            }
                            __strong typeof(wSelf) strongSelf = wSelf;
            
                            [strongSelf.processChain logNodeEvent:[NSString stringWithFormat:@"timeout, %@ before goDie", [strongSelf name4log]]];
            
                            [strongSelf goDie:@{@"why":             @"timeout",
                                                @"timeOut4Process": @(strongSelf.timeOut4Process)}];
        });
    }
    
    __weak typeof(self) weakSelf = self;
    excuteInQueue(self.forceMainThread, ^{
        if(! weakSelf) {
            return;
        }
        __strong typeof(weakSelf) strongSelf = weakSelf;
        strongSelf.beginWorkTs = [[NSDate alloc]init];
        [strongSelf ready2work:nil];
    });
    
}

// 需要重写 默认动作是调用 goSucc
-(void) ready2work:(NSDictionary * _Nullable)startInfo {
    [self goSucc:nil];
}

// 需要重载，默认解除节点之间的相互，在处理链结束前被调用
-(void) cleanBeforeStop {
    [self.preNodeList removeAllObjects];
    self.processChain = nil;
}

-(void) goDie:(NSDictionary * _Nullable)dieInfo {
    @synchronized (self) {
        if(_processStatus != TBProcessNodeMCStatusWorking) {
            [_processChain logNodeEvent:[NSString stringWithFormat:@"goDie, %@, _processStatus != TBProcessNodeMCStatusWorking, no operation", [self name4log]]];
            return;
        }
        _processStatus = TBProcessNodeMCStatusGoDie;
    }
    self.endWorkTs = [[NSDate alloc]init];
    //this.showFlash();

    if (self.processChain) {
        NSMutableDictionary *mInfo = [NSMutableDictionary dictionaryWithDictionary:(dieInfo ?: @{})];
        if([self.nodeName length]> 0) {
            mInfo[@"goDie_NodeName"] = self.nodeName;
        } else {
            mInfo[@"goDie_NodeClass"] = NSStringFromClass(self.class);
        }
        [self.processChain handleNodeGoDie:self dieInfo:[mInfo copy]];
    }
}

-(void) goSucc:(NSDictionary * _Nullable)succInfo {
    @synchronized (self) {
        if(_processStatus != TBProcessNodeMCStatusWorking) {
            [_processChain logNodeEvent:[NSString stringWithFormat:@"goSucc, %@, _processStatus != TBProcessNodeMCStatusWorking, no operation", [self name4log]]];
            return;
        }
        _processStatus = TBProcessNodeMCStatusGoSucc;
    }
    self.endWorkTs = [[NSDate alloc]init];
    //this.showFlash();

    if (self.processChain) {
        [self.processChain handleNodeFinish:self succInfo:succInfo];
    }
}



// 添加强关联的 前置节点
-(void) addStrongPreNode:(TBProcessNodeMC *)preNode {
    [self addPreNode:preNode preStrong:YES];
}

// 添加弱关联的 前置节点
-(void) addWeakPreNode:(TBProcessNodeMC *)preNode {
    [self addPreNode:preNode preStrong:NO];
}

// 添加前置节点
-(void) addPreNode:(TBProcessNodeMC *)preNode preStrong:(BOOL)preStrong {

    if(preNode==nil || preNode == self) {
        return;
    }

    // _preNodeList 并联前置节点数组，偶数下标存放前置节点对象，奇数下标存放前置节点和自身的强弱关系
    @synchronized (_preNodeList) {
        // 遍历查看是否已经存在，如果已经存在就不添加节点了，强弱关系修改成形参中的值
        int indexOfExist = -1;
        for(int loop=0; loop < [_preNodeList count]; loop += 2) {
            TBProcessNodeMC* sNode = (TBProcessNodeMC*) (_preNodeList[loop]);
            if(sNode == preNode) {
                indexOfExist = loop;
                break;
            }
        }

        if(indexOfExist >= 0) {
            // 如果已经存在, 强弱关系修改成形参中的值
            _preNodeList[indexOfExist + 1] = @(preStrong);
        } else {
            // 不存在，添加节点
            [_preNodeList addObject:preNode];
            [_preNodeList addObject:@(preStrong)];
        }
    }
}

// 根据串并联和强弱前置关系，推动节点行动
-(void) checkPreNodes2work:(TBProcessNodeMC *)processNode {

    if(!processNode) {
        return;
    }

    if(_processStatus != TBProcessNodeMCStatusNotWork) {
        // 当前节点不处于 未启动状态
        return;
    }

    if(! [_preNodeList containsObject:processNode]) {
        // 不是当前节点感兴趣的 trigger节点
        return;
    }

    // 这是感兴趣的前置节点，接着往下处理
    //this.showInfo(this.getClass().getSimpleName()+" get intrested trigger node:" + triggerNode.getClass().getSimpleName());

    // 遍历前置节点
    TBProcessNodeMC *pNode = nil;
    BOOL preNodeAllFinish = YES;
    
    for (int loop=0; loop < [_preNodeList count]; loop += 2) {
        
        pNode = (TBProcessNodeMC*)(_preNodeList[loop]);
        BOOL isStrong = [(_preNodeList[loop+1]) boolValue];
        
        if (! [pNode isWorkStatusFinish]) {
            preNodeAllFinish = NO;
        }

        if (isStrong && pNode.processStatus == TBProcessNodeMCStatusGoDie) {
            // 强前置节点 gg，这个节点也 gg
            [self goDie:@{@"why" : @"strong pre node die"}];
            return;
        } else {
            // 弱并联前置节点 gg，无所谓
        }

    }
    
    if (preNodeAllFinish) {
        // 前置节点满足，开启当前节点的处理逻辑
        [_processChain logNodeEvent:[NSString stringWithFormat:@"checkPreNodes2work, %@ done, %@ 前置节点满足，启动节点，%.2f",
              [processNode name4log],
              [self name4log],
              1000.f*([NSDate new].timeIntervalSince1970 - processNode.beginWorkTs.timeIntervalSince1970)]];
        
        [self forceBegin];
    } else {
        
        [_processChain logNodeEvent:[NSString stringWithFormat:@"checkPreNodes2work, %@ done, but %@ 前置节点不满足 %.2f",
              [processNode name4log],
              [self name4log],
              1000.f*([NSDate new].timeIntervalSince1970 - processNode.beginWorkTs.timeIntervalSince1970)]];
    }
}

// https://blog.csdn.net/login_sonata/article/details/78002042
// 检测有向图中是否有环, 如果有环，返回包含环的数组，最后一个元素就是环的头
// 所有访问过的 节点记录到 allNodesVisited，如果正常，应该和处理链中的node集合相同。
// 所有访问到的 没有前置节点的 node 记录到 allNodesThatNoPre，如果正常应该只有1个，且等于处理链的开始节点
+ (NSArray<TBProcessNodeMC *> *) applyDFS2DetectLoopFromFinishNode:(TBProcessNodeMC *)currentNode
                      chainNodesFromFinish:(NSMutableArray<TBProcessNodeMC *> *)chainNodesFromFinish
                           allNodesVisited:(NSMutableSet<TBProcessNodeMC *> *)allNodesVisited
                         allNodesThatNoPre:(NSMutableSet<TBProcessNodeMC *> *)allNodesThatNoPre {
    
    if([chainNodesFromFinish containsObject:currentNode]) {
        // 当前节点 在 “由结束节点向前递归的处理链”中出现, 表示发现环
        // 返回的数组中，最后一个元素就是环的头
        [chainNodesFromFinish addObject:currentNode];
        return chainNodesFromFinish;
    }
    // 当前节点 加入 “由结束节点向前递归的处理链” 中
    [chainNodesFromFinish addObject:currentNode];
    
    // 当前节点记录到 allNodesVisited
    [allNodesVisited addObject:currentNode];
    
    if([currentNode.preNodeList count] == 0) {
        // 当前节点没有 前置节点，计入 allNodesThatNoPre 中
        [allNodesThatNoPre addObject:currentNode];
    }
    
    // 处理链 终止 节点的 绘制坐标设定为 (0,0)
    if(currentNode.cx < 0) {
        currentNode.cx = 0;
    }
    if(currentNode.cy < 0) {
        currentNode.cy = 0;
    }

    // 一条深度遍历路线 preNodeVistList 中如果 有结点被第二次访问到，那么有环。
    int deltaY = 0;
    for (int loop=0, n=0; loop < [currentNode.preNodeList count]; loop += 2, n += 1) {
        
        TBProcessNodeMC * preNode = (TBProcessNodeMC*)(currentNode.preNodeList[loop]);
        
        // 绘制处理链，前置节点绘制坐标X设定为不小于 当前节点X+1
        if(preNode.cx < currentNode.cx+1) {
            preNode.cx = currentNode.cx+1;
        }
        // 绘制处理链，第n个前置节点绘制坐标Y设定为不小于 当前节点X+n
        int targetCY = currentNode.cy+n+deltaY;
        if(preNode.cy < targetCY) {
            preNode.cy = targetCY;
        } else if(preNode.cy == targetCY) {
            deltaY += 1; //额外的y方向偏移，绘制处理链图片时候防止有向线段重合用
            preNode.cy = targetCY+1;
        }
        
        // 深度 优先 递归
        NSArray<TBProcessNodeMC *> *loopNodes = [self applyDFS2DetectLoopFromFinishNode:preNode
                                          chainNodesFromFinish:[NSMutableArray arrayWithArray:chainNodesFromFinish]
                                               allNodesVisited:allNodesVisited
                                             allNodesThatNoPre:allNodesThatNoPre];

        // 如果发现环，返回描述环的 数组
        if([loopNodes count]>0) {
            return loopNodes;
        }
        
        //[visitCopyList removeAllObjects];
        //visitCopyList = nil;
    }

    return nil;
}

- (nullable id)safeGetSharedInfo:(nonnull id)key {
    if(! key) {
        return nil;
    }
    @synchronized (self.processChain.processSharedInfo) {
        id value = [self.processChain.processSharedInfo objectForKey:key];
        return value;
    }
}

- (void)safeSetSharedInfo:(nonnull id)key value:(nullable id)value {
    if(! key) {
        return;
    }
    @synchronized (self.processChain.processSharedInfo) {
        self.processChain.processSharedInfo[key] = value;
    }
}


@end
